;;;;;; numbers.scm - Scheme Numeric Utility module.    -*- Mode: Scheme -*-
;;;;;; Author: Erik Silkensen <silkense@colorado.edu>
;;;;;; Version: 31 May 2009

#lang scheme

;;; <number> -> <num 2> | <num 8>
;;;          | <num 10> | <num 16>
;;; <num R> -> <prefix R> <complex R>
;;; <complex R> -> <real R> | <real R> @ <real R>
;;;          | <real R> + <ureal R> i | <real R> - <ureal R> i
;;;          | <real R> + i | <real R> - i
;;;          | + <ureal R> i | - <ureal R> i 
;;;          | + i | - i
;;; <real R> -> <sign> <ureal R>
;;; <ureal R> -> <uinteger R>
;;;          | <uinteger R> / <uinteger R>
;;;          | <decimal R>
;;; <decimal 10> -> <uinteger 10> <suffix>
;;;          | . <digit 10>+ <suffix>
;;;          | <digit 10>+ . <digit 10>* <suffix>
;;;          | <digit 10>+ . <suffix>
;;; <uinteger R> -> <digit R>+
;;; <prefix R> -> <radix R> <exactness>
;;;          | <exactness> <radix R>
;;; <suffix> -> <empty> 
;;;          | <exponent marker> <sign> <digit 10>+
;;; <exponent marker> -> e | E | s | S | f | F
;;;          | d | D | l | L
;;; <sign> -> <empty> | + | -
;;; <exactness> -> <empty>
;;;          | #i| #I | #e| #E
;;; <radix 2> -> #b| #B
;;; <radix 8> -> #o| #O
;;; <radix 10> -> <empty> | #d | #D
;;; <radix 16> -> #x| #X
;;; <digit 2> -> 0 | 1
;;; <digit 8> -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
;;; <digit 10> -> <digit>
;;; <digit 16> -> <hex digit>

(provide (all-defined-out))

(define (char-exactness? char)
  (case (char-downcase char)
    ((#\i #\e) #t)
    (else #f)))

(define (char-numeric-2? char)
  (or (char=? #\0 char)
      (char=? #\1 char)))

(define (char-numeric-8? char)
  (let ((ord (char->integer char)))
    (and (>= ord #x30)
         (<= ord #x37))))

(define (char-numeric-16? char)
  (or (char-numeric? char)
      (let ((ord (char->integer (char-downcase char))))
        (and (>= ord #x61)
             (<= ord #x66)))))

(define (char-radix? char)
  (case (char-downcase char)
    ((#\b #\d #\o #\x) #t)
    (else #f)))

(define (char-exponent-marker? char)
  (case (char-downcase char)
    ((#\e #\s #\f #\d #\l) #t)
    (else #f)))

(define (char-radix->digits? radix)
  (case (char-downcase radix)
    ((#\b) char-numeric-2?)
    ((#\d) char-numeric?)
    ((#\o) char-numeric-8?)
    ((#\x) char-numeric-16?)
    (else (lambda (x) #f))))

(define (radix->digits? radix)
  (case radix
    ((2) char-numeric-2?)
    ((10) char-numeric?)
    ((8) char-numeric-8?)
    ((16) char-numeric-16?)
    (else (lambda (x) #f))))

(define (char-sign? char)
  (or (char=? #\+ char)
      (char=? #\- char)))
